package com.yl.chainStore.services.impl.warehouse


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.yl.chainStore.common.enums.Status
import com.yl.chainStore.common.enums.TypeEnum
import com.yl.chainStore.entity.pay.PayCompanyDeptItem
import com.yl.chainStore.entity.pay.SysCompanyPayItemType
import com.yl.chainStore.entity.pay.SysCompanyPayItem
import com.yl.chainStore.entity.warehouse.*
import com.yl.chainStore.mapper.pay.PayCompanyDeptItemMapper
import com.yl.chainStore.mapper.pay.SysCompanyPayItemMapper
import com.yl.chainStore.mapper.pay.SysCompanyPayItemTypeMapper
import com.yl.chainStore.mapper.warehouse.*
import com.yl.chainStore.pojo.vo.pay.SystemCompanyPayItemSelectVo
import com.yl.chainStore.pojo.vo.warehouse.*
import com.yl.chainStore.services.IWebCompanyDeptService
import com.yl.chainStore.services.IWebSystemService
import com.yl.chainStore.services.pay.ISysCompanyPayItemService
import com.yl.chainStore.services.warehouse.IWarehouseService
import com.yl.common.ErrorCode
import com.yl.common.control.ResponseBody
import com.yl.common.control.returnError
import com.yl.common.control.returnSuccess
import com.yl.common.getContext
import com.yl.users.services.ICompanyDeptService
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.util.*

@Service
class WarehouseServiceImpl(
	private val sysCompanyPayItemTypeMapper: SysCompanyPayItemTypeMapper,
	private val sysCompanyPayItemMapper: SysCompanyPayItemMapper,
	private val payCompanyDeptItemMapper: PayCompanyDeptItemMapper,
	private val warehouseGoodSupplierMapper: WarehouseGoodSupplierMapper,
	private val warehouseGoodUpdateLogMapper: WarehouseGoodUpdateLogMapper,
	private val warehouseGoodBatchCountMapper: WarehouseGoodBatchCountMapper,

	private val warehouseInOrderMapper: WarehouseInOrderMapper,
	private val warehouseOutOrderMapper: WarehouseOutOrderMapper,
	private val warehouseDispatchOrderMapper: WarehouseDispatchOrderMapper,
	private val warehouseCheckOrderMapper: WarehouseCheckOrderMapper,
	private val warehouseProfitLossOrderMapper: WarehouseProfitLossOrderMapper,
) : IWarehouseService {

	@Autowired
	lateinit var iWebSystemService: IWebSystemService

	@Autowired
	lateinit var iWebCompanyDeptService: IWebCompanyDeptService

	@Autowired
	lateinit var iCompanyDeptService: ICompanyDeptService

	@Autowired
	lateinit var iSysCompanyPayItemService: ISysCompanyPayItemService


	companion object {
		private val log = LoggerFactory.getLogger(IWarehouseService::class.java)
	}

	override fun getGoodTypeList(subCompanyId: Long): MutableList<SysCompanyPayItemType> {
		log.info("仓库操作 ===> 获取仓库收费项目类型 deptId：{}", subCompanyId)
		val queryWrapper = QueryWrapper<SysCompanyPayItemType>().eq("enabled",1)
		queryWrapper.and {
			queryWrapper->queryWrapper.eq("dept_id", subCompanyId).or().isNull("dept_id")
		}
		queryWrapper.`in`(
			"item_type", TypeEnum.PAY_ITEM_CONSUMABLES, TypeEnum.PAY_ITEM_GOODS
		)
		return sysCompanyPayItemTypeMapper.selectList(queryWrapper)
	}

	override fun addGoodType(type: SysCompanyPayItemType): ResponseBody {
		log.info("仓库操作 ===> 添加仓库收费项目类型 type：{}", type)
		if (type.deptId == null) {
			type.deptId = getContext().subCompanyId
		}
		if(type.superId == 0L){
			if(type.itemType != TypeEnum.PAY_ITEM_GOODS && type.itemType != TypeEnum.PAY_ITEM_CONSUMABLES){
				return returnError(ErrorCode.DATA_SAVE_FAILED,"类型选择错误")
			}
		}
		return iWebSystemService.addItemType(type)
	}

	override fun getGoodPage(
		page: Page<SysCompanyPayItem>,
		vo: SystemCompanyPayItemSelectVo,
		deptId: Long
	): Page<SysCompanyPayItem> {
		log.info("仓库管理 ==> 物品列表 count:{}", vo)
		vo.types = listOf(TypeEnum.PAY_ITEM_GOODS, TypeEnum.PAY_ITEM_CONSUMABLES)
		return sysCompanyPayItemMapper.deptSelectItemPage(page, vo, vo.typeId, deptId)
	}


	override fun addPayItem(item: SysCompanyPayItem, vo: UpdateItemConfigVo): ResponseBody {
		log.info("仓库操作 ===> 添加物品（收费项目） item：{}，vo:{}", item,vo)
		if (item.deptId == null) {
			item.deptId = getContext().subCompanyId
		}

		val result = iWebSystemService.addPayItem(item)
		if (result.code != ErrorCode.SUCCESS.code) {
			return result
		}
		vo.deptId = item.deptId!!
		vo.itemId = item.id

		return iSysCompanyPayItemService.setPayItemDeptConfig(vo)

	}


	override fun addSupplier(supplier: WarehouseGoodSupplier): ResponseBody {
		log.info("仓库管理 ==> 添加供应商 supplier:{}", supplier)

		if (supplier.name.isBlank()) {
			return returnError(ErrorCode.PARAM_EMPTY, "请输入厂商名称")
		}
		supplier.deptId = getContext().subCompanyId
		warehouseGoodSupplierMapper.insert(supplier)
		return returnSuccess()
	}

	override fun supplierList(vo: WarehouseGoodSupplierSelectVo): List<WarehouseGoodSupplier> {
		log.info("仓库管理 ==> 供应商列表 vo:{}", vo)
		return warehouseGoodSupplierMapper.selectSupplierList(vo)
	}

	override fun supplierPage(
		page: Page<WarehouseGoodSupplier>,
		vo: WarehouseGoodSupplierSelectVo
	): Page<WarehouseGoodSupplier> {
		log.info("仓库管理 ==> 供应商分页 vo:{},page:{}", vo, page)
		return warehouseGoodSupplierMapper.selectSupplierPage(page, vo)
	}

	override fun inWarehouse(goodBatchId:Long?,updateVo: UpdateWarehouseGoodVo): ResponseBody {
		log.info("仓库管理 ==> 入库 goodBatchId:{}, updateVo:{}",goodBatchId, updateVo)
		val warehouseGoodBatchCount:WarehouseGoodBatchCount
		if(goodBatchId == null){
			 warehouseGoodBatchCount = WarehouseGoodBatchCount(
				itemId = updateVo.itemId,
				goodCount = updateVo.goodCount,
				companyId = updateVo.companyId,
				goodLeftCount = updateVo.goodCount,
				deptId = updateVo.deptId,
				goodPrice = updateVo.unitPrice
			)
			warehouseGoodBatchCountMapper.insert(warehouseGoodBatchCount)
		}else{
			warehouseGoodBatchCount = warehouseGoodBatchCountMapper.selectById(goodBatchId)
			warehouseGoodBatchCountMapper.addCount(goodBatchId,updateVo.goodCount)
		}

		val queryWrapper = QueryWrapper<PayCompanyDeptItem>()
		queryWrapper.eq("company_id", updateVo.companyId).eq("dept_id", updateVo.deptId)
			.eq("item_id", updateVo.itemId)
		var sumCount = payCompanyDeptItemMapper.selectOne(queryWrapper)
		if (sumCount != null) {
			payCompanyDeptItemMapper.addCount(sumCount.id, updateVo.goodCount)
			payCompanyDeptItemMapper.addSumMoney(sumCount.id, updateVo.unitPrice * updateVo.goodCount)
		} else {
			sumCount = PayCompanyDeptItem(
				itemId = updateVo.itemId,
				companyId = updateVo.companyId,
				deptId = updateVo.deptId,
				count = updateVo.goodCount,
				warehouseSumMoney = updateVo.unitPrice * updateVo.goodCount
			)
			payCompanyDeptItemMapper.insert(sumCount)
		}

		warehouseGoodUpdateLogMapper.insert(
			WarehouseGoodUpdateLog(
				associatedType = updateVo.associatedType,
				associatedId = updateVo.associatedId,
				remark = updateVo.remark,
				deptId = updateVo.deptId,
				companyId = updateVo.companyId,
				itemId = updateVo.itemId,
				goodCount = updateVo.goodCount,
				detailId = updateVo.detailId,
				beforeSumCount = 0,
				afterSumCount = sumCount.count,
				beforeBatchCount = 0,
				afterBatchCount = updateVo.goodCount,
				batchCountId = warehouseGoodBatchCount.id
			)
		)
		log.info("仓库管理 ==> 入库成功")
		return returnSuccess()
	}

	override fun outWarehouse(goodBatchId: Long?, updateLog: UpdateWarehouseGoodVo): ResponseBody {
		log.info("仓库管理 ==> 出库 log:{}", updateLog)

		return if (goodBatchId != null) {
			outWarehouseHaveBatchId(goodBatchId, updateLog)
		} else {
			outWarehouseNotHaveBatchId(updateLog)
		}
	}

	private fun outWarehouseHaveBatchId(goodBatchId: Long, updateVo: UpdateWarehouseGoodVo): ResponseBody {
		log.info("仓库管理 ==> 出库 goodBatchId:{},updateVo:{}", goodBatchId,updateVo)
		val batchCount = warehouseGoodBatchCountMapper.selectById(goodBatchId) ?: return returnError(
			ErrorCode.DATA_IS_NOT_FIND,
			"未找到该批次物品"
		)
		if (batchCount.goodLeftCount < updateVo.goodCount) {
			return returnError(
				ErrorCode.OPERATION_DATA_ERROR,
				"批次物品数量不足"
			)
		}
		val queryWrapper = QueryWrapper<PayCompanyDeptItem>()
		queryWrapper.eq("company_id", updateVo.companyId).eq("dept_id", updateVo.deptId)
			.eq("item_id", updateVo.itemId)
		val sumCount = payCompanyDeptItemMapper.selectOne(queryWrapper)
			?: return returnError(
				ErrorCode.OPERATION_DATA_ERROR,
				"仓库物品不存在 "
			)
		if (sumCount.count < updateVo.goodCount) {
			return returnError(
				ErrorCode.OPERATION_DATA_ERROR,
				"仓库物品数量不足"
			)
		}
		warehouseGoodBatchCountMapper.subCount(goodBatchId, updateVo.goodCount)
		payCompanyDeptItemMapper.subCount(sumCount.id, updateVo.goodCount)
		payCompanyDeptItemMapper.subSumMoney(sumCount.id, batchCount.goodPrice * updateVo.goodCount)
		val resList = mutableListOf<OutBatchCountVo>()
		warehouseGoodUpdateLogMapper.insert(
			WarehouseGoodUpdateLog(
				associatedType = updateVo.associatedType,
				associatedId = updateVo.associatedId,
				remark = updateVo.remark,
				deptId = updateVo.deptId,
				companyId = updateVo.companyId,
				itemId = updateVo.itemId,
				goodCount = updateVo.goodCount,
				detailId = updateVo.detailId,
				beforeSumCount = sumCount.count,
				afterSumCount = sumCount.count - updateVo.goodCount,
				beforeBatchCount = batchCount.goodLeftCount,
				afterBatchCount = batchCount.goodLeftCount - updateVo.goodCount,
				batchCountId = batchCount.id
			)
		)
		resList.add(
			OutBatchCountVo(
				batchCount.id,
				updateVo.goodCount,
				batchCount.goodPrice
			)
		)
		log.info("仓库管理 ==> 单批次出库成功")
		return returnSuccess(resList)
	}

	private fun outWarehouseNotHaveBatchId(updateVo: UpdateWarehouseGoodVo): ResponseBody {
		log.info("仓库管理 ==> 出库 updateVo:{}",updateVo)
		val queryWrapper = QueryWrapper<PayCompanyDeptItem>()
		queryWrapper.eq("company_id", updateVo.companyId).eq("dept_id", updateVo.deptId)
			.eq("item_id", updateVo.itemId)
		var sumCount = payCompanyDeptItemMapper.selectOne(queryWrapper) ?: return returnError(
			ErrorCode.OPERATION_DATA_ERROR,
			"仓库物品不存在"
		)
		if (sumCount.count < updateVo.goodCount) {
			return returnError(
				ErrorCode.OPERATION_DATA_ERROR,
				"物品数量不足"
			)
		}

		val wrapper = QueryWrapper<WarehouseGoodBatchCount>()
		wrapper.eq("company_id", updateVo.companyId)
			.eq("dept_id", updateVo.deptId)
			.eq("item_id", updateVo.itemId)
			.gt("good_left_count", 0).orderByAsc("create_time")
		val batchCounts = warehouseGoodBatchCountMapper.selectList(wrapper)

		var goodCount = updateVo.goodCount
		val resList = mutableListOf<OutBatchCountVo>()
		for (count in batchCounts) {
			//循环取出批次列表出库
			if (count.goodLeftCount >= goodCount) {
				//批次部分出库(剩下的数量可以一次出完)
				warehouseGoodBatchCountMapper.subCount(count.id, goodCount)
				//这里只需更新后跳出，所以不用刷新
				payCompanyDeptItemMapper.subCount(sumCount.id, goodCount)
				payCompanyDeptItemMapper.subSumMoney(sumCount.id, count.goodPrice * goodCount)
				warehouseGoodUpdateLogMapper.insert(
					WarehouseGoodUpdateLog(
						associatedType = updateVo.associatedType,
						associatedId = updateVo.associatedId,
						remark = updateVo.remark,
						deptId = updateVo.deptId,
						companyId = updateVo.companyId,
						itemId = updateVo.itemId,
						goodCount = goodCount,
						detailId = updateVo.detailId,
						beforeSumCount = sumCount.count,
						afterSumCount = sumCount.count - updateVo.goodCount,
						beforeBatchCount = count.goodLeftCount,
						afterBatchCount = count.goodLeftCount - updateVo.goodCount,
						batchCountId = count.id
					)
				)
				resList.add(
					OutBatchCountVo(
						count.id,
						goodCount,
						count.goodPrice
					)
				)
				goodCount -= goodCount

				//这边直接跳出了，所以不用
				break
			} else {
				//批次全部出库
				resList.add(
					OutBatchCountVo(
						count.id,
						count.goodLeftCount,
						count.goodPrice
					)
				)
				goodCount -= count.goodLeftCount
				warehouseGoodBatchCountMapper.subCount(count.id, count.goodLeftCount)
				//更新总数并刷新获取总数数量
				payCompanyDeptItemMapper.subCount(sumCount.id, count.goodLeftCount)
				payCompanyDeptItemMapper.subSumMoney(sumCount.id, count.goodPrice * count.goodLeftCount)
				warehouseGoodUpdateLogMapper.insert(
					WarehouseGoodUpdateLog(
						associatedType = updateVo.associatedType,
						associatedId = updateVo.associatedId,
						remark = updateVo.remark,
						deptId = updateVo.deptId,
						companyId = updateVo.companyId,
						itemId = updateVo.itemId,
						goodCount = count.goodLeftCount,
						detailId = updateVo.detailId,
						beforeSumCount = sumCount.count,
						afterSumCount = sumCount.count - count.goodLeftCount,
						beforeBatchCount = count.goodLeftCount,
						afterBatchCount = 0,
						batchCountId = count.id
					)
				)
				sumCount = payCompanyDeptItemMapper.selectById(sumCount.id)
			}
		}
		if (goodCount != 0) {
			return returnError(
				ErrorCode.OPERATION_DATA_ERROR,
				"物品数量不足"
			)
		}


		log.info("仓库管理 ==> 多批次出库成功")
		return returnSuccess(resList)
	}

	override fun getGoodBatchCount(id: Long): WarehouseGoodBatchCount? {
		log.info("仓库管理 ==> 获取物品批次数量 id:{}",id)
		return warehouseGoodBatchCountMapper.selectById(id)
	}

	override fun getLastBatchCount(companyId: Long, deptId: Long, itemId: Long): WarehouseGoodBatchCount? {
		log.info("仓库管理 ==> 最后一次的入库批次 companyId:{}，deptId：{}，itemId：{}",companyId,deptId,itemId)
		val wrapper = QueryWrapper<WarehouseGoodBatchCount>()

		wrapper.eq("company_id", companyId)
			.eq("dept_id", deptId)
			.eq("item_id", itemId)
			.orderByDesc("create_time")
			.last("LIMIT 1")
		return warehouseGoodBatchCountMapper.selectOne(wrapper)
	}

	override fun getGoodsSumCount(companyId: Long, deptId: Long, itemId: Long): Int? {
		log.info("仓库管理 ==> 物品总数 companyId:{}，deptId：{}，itemId：{}",companyId,deptId,itemId)

		val wrapper = QueryWrapper<PayCompanyDeptItem>()
		wrapper.eq("company_id", companyId)
			.eq("dept_id", deptId)
			.eq("item_id", itemId)
			.orderByDesc("create_time")
			.last("LIMIT 1")
		return payCompanyDeptItemMapper.selectOne(wrapper)?.count
	}

	override fun addInOrder(inOrder: WarehouseInOrder): ResponseBody {
		log.info("仓库管理：申请入库单：inOrder{}", inOrder)
		if (inOrder.type == TypeEnum.WAREHOUSE_IN_TYPE_SUPPLIER && inOrder.supplierId == null) {
			return returnError(ErrorCode.PARAM_EMPTY, "请选择供应商")
		}
		if (inOrder.type == TypeEnum.WAREHOUSE_IN_TYPE_DEPT && inOrder.inWarehouseDeptId == null) {
			return returnError(ErrorCode.PARAM_EMPTY, "请选择退领部门")
		}
		if (inOrder.type == TypeEnum.WAREHOUSE_IN_TYPE_USER && inOrder.inWarehouseUserId == null) {
			return returnError(ErrorCode.PARAM_EMPTY, "请选择退领人员")
		}
		if (inOrder.details.isNullOrEmpty()) {
			return returnError(ErrorCode.PARAM_EMPTY, "请填写入库物品")
		}
		if (inOrder.orderTime == null) {
			inOrder.orderTime = Date()
		}
		if (inOrder.inUserId == null) {
			inOrder.inUserId = inOrder.createUserId
		}
		inOrder.status = Status.WAIT_AUDIT
		warehouseInOrderMapper.insert(inOrder)
		return returnSuccess()
	}

	override fun inOrderPage(page: Page<WarehouseInOrder>, inOrder: WarehouseInOrderSelectVo): Page<WarehouseInOrder> {
		log.info("仓库管理：入库分页查询：inOrder{}", inOrder)
		return warehouseInOrderMapper.getInorderPage(page, inOrder, Status.STAGING)
	}

	override fun addOutOrder(outOrder: WarehouseOutOrder): ResponseBody {
		log.info("仓库管理：添加出库单：outOrder{}", outOrder)
		if (outOrder.type == TypeEnum.WAREHOUSE_OUT_TYPE_SUPPLIER && outOrder.supplierId == null) {
			return returnError(ErrorCode.PARAM_EMPTY, "请选择供应商")
		}
		if (outOrder.type == TypeEnum.WAREHOUSE_OUT_TYPE_DEPT && outOrder.outWarehouseDeptId == null) {
			return returnError(ErrorCode.PARAM_EMPTY, "请选择领用部门")
		}
		if (outOrder.type == TypeEnum.WAREHOUSE_OUT_TYPE_USER && outOrder.outWarehouseUserId == null) {
			return returnError(ErrorCode.PARAM_EMPTY, "请选择领用人员")
		}
		if (outOrder.type == TypeEnum.WAREHOUSE_OUT_TYPE_ORDER && outOrder.outWarehouseUserId == null) {
			return returnError(ErrorCode.PARAM_EMPTY, "请选择销售订单")
		}

		if (outOrder.details.isNullOrEmpty()) {
			return returnError(ErrorCode.PARAM_EMPTY, "请填写出库物品")
		}
		if (outOrder.orderTime == null) {
			outOrder.orderTime = Date()
		}
		if (outOrder.outUserId == null) {
			outOrder.outUserId = outOrder.createUserId
		}
		outOrder.status = Status.WAIT_AUDIT
		warehouseOutOrderMapper.insert(outOrder)
		return returnSuccess()
	}

	override fun outOrderPage(
		page: Page<WarehouseOutOrder>,
		outOrder: WarehouseOutOrderSelectVo
	): Page<WarehouseOutOrder> {
		log.info("仓库管理：出库单分页：outOrder{}", outOrder)

		return warehouseOutOrderMapper.selectOutOrderPage(page, outOrder, Status.STAGING)
	}

	override fun addDispatchOrder(dispatchOrder: WarehouseDispatchOrder): ResponseBody {
		log.info("仓库管理：添加调度单：dispatchOrder{}", dispatchOrder)
		if (dispatchOrder.inDeptId != 0L) {
			iCompanyDeptService.getDept(dispatchOrder.inDeptId) ?: return returnError(
				ErrorCode.DATA_IS_NOT_FIND,
				"调入仓库未找到"
			)
		}
		if (dispatchOrder.outDeptId != 0L) {
			iCompanyDeptService.getDept(dispatchOrder.outDeptId) ?: return returnError(
				ErrorCode.DATA_IS_NOT_FIND,
				"调出仓库未找到"
			)
		}
		if (dispatchOrder.details == null) {
			return returnError(ErrorCode.PARAM_EMPTY, "请填写调度物品详情")
		}
		if (dispatchOrder.orderTime == null) {
			dispatchOrder.orderTime = Date()
		}
		dispatchOrder.inStatus = Status.WAIT_AUDIT
		dispatchOrder.outStatus = Status.WAIT_AUDIT
		warehouseDispatchOrderMapper.insert(dispatchOrder)
		return returnSuccess()
	}

	override fun dispatchOrderPage(
		page: Page<WarehouseDispatchOrder>,
		dispatchOrder: WarehouseDispatchOrderSelectVo
	): Page<WarehouseDispatchOrder> {
		log.info("仓库管理：调度单分页：dispatchOrder{}", dispatchOrder)
		return warehouseDispatchOrderMapper.getDispatchPage(page, dispatchOrder)
	}

	override fun addCheckOrder(checkOrder: WarehouseCheckOrder): ResponseBody {
		log.info("仓库管理：盘点：添加盘点信息 checkOrder{}", checkOrder)
		if (checkOrder.checkUserId == null) {
			checkOrder.checkUserId = getContext().userId
		}
		checkOrder.status = Status.WAIT_AUDIT
		warehouseCheckOrderMapper.insert(checkOrder)
		return returnSuccess()
	}

	override fun checkOrderPage(
		page: Page<WarehouseCheckOrder>,
		checkOrder: WarehouseCheckOrderSelectVo
	): Page<WarehouseCheckOrder> {
		log.info("仓库管理：盘点：盘点单分页查询：page：{} checkOrder{}",page, checkOrder)

		return warehouseCheckOrderMapper.selectOrderPage(page, checkOrder)
	}

	override fun addProfitLossOrder(order: WarehouseProfitLossOrder): ResponseBody {
		log.info("仓库管理 ==> 新增损益单：order:{}",order)
		order.status = Status.WAIT_AUDIT
		warehouseProfitLossOrderMapper.insert(order)
		return returnSuccess()
	}

	override fun profitLossPage(
		page: Page<WarehouseProfitLossOrder>,
		vo: WarehouseProfitLossOrderSelectVo
	): Page<WarehouseProfitLossOrder> {
		log.info("仓库管理 ==> 损益单分页查询：page{},vo:{}",page,vo)
		return warehouseProfitLossOrderMapper.getOrderPage(page,vo,Status.STAGING)
	}
}
